/*
 * @Author: Turump 
 * @Date: 2021-04-02 11:48:33 
 * @Last Modified by: Turump
 * @Last Modified time: 2022-01-10 16:12:00
 * 播放帧动画
 */

//帧间过渡类型
enum FrameTransitionType {
    None,   //无过度，传统的帧动画
    FadeIn, //新帧淡入
}

import { TaskBase } from "./TaskBase";

const { ccclass, property, menu, requireComponent } = cc._decorator;

@ccclass
@menu("任务组件/播放帧动画")
@requireComponent(cc.Sprite)
export default class SpriteFrameAniTask extends TaskBase {

    @property({ displayName: "图片帧", type: [cc.SpriteFrame] })
    picFrames: cc.SpriteFrame[] = []

    @property({ displayName: "帧间隔(s)" })
    frameDuration = 0.5

    @property({ displayName: "循环播放" })
    loop = false;

    @property({ displayName: "首帧无间隔" })
    firstFrameNoDelay = false;

    @property({ displayName: "自定义帧序列", tooltip: "图片帧从0开始计数" })
    isDefineFrames = false;

    @property({ displayName: "自定义序列", tooltip: "分号隔开", visible() { return this.isDefineFrames } })
    frameIndexString = ""

    @property({ displayName: "过渡类型", type: cc.Enum(FrameTransitionType) })
    transitionType: FrameTransitionType = FrameTransitionType.None;

    private currentIndex = 0;
    private isPaused = true;

    frameIndexArray: number[] = []
    onLoad() {
        super.onLoad();
        if (this.isDefineFrames == false) {
            this.frameIndexArray = [...Array(this.picFrames.length)].map((k, i) => i);
        } else {
            let arr = this.frameIndexString.split(';')
            this.frameIndexArray = arr.map(x => parseInt(x))
        }

        if (this.transitionType == FrameTransitionType.FadeIn) {
            let tranNode = new cc.Node("TransitionNode");
            let spr = tranNode.addComponent(cc.Sprite);
            tranNode.parent = this.node
            tranNode.setAnchorPoint(this.node.getAnchorPoint());
            tranNode.position = cc.v3(0, 0);

            let thisNodeSpr = this.node.getComponent(cc.Sprite);
            spr.trim = thisNodeSpr.trim;
            spr.type = thisNodeSpr.type;
            spr.sizeMode = thisNodeSpr.sizeMode;
            spr.spriteFrame = this.picFrames[this.frameIndexArray[this.currentIndex]]
            tranNode.opacity = 0;
        }
    }

    enableTask() {
        super.enableTask();
        this.isPaused = false;
        this.firstFrameNoDelay
            && (this.node.getComponent(cc.Sprite).spriteFrame = this.picFrames[this.frameIndexArray[0]])
    }

    changeFrame() {
        let frameIndex = this.frameIndexArray[this.currentIndex]
        this.node.getComponent(cc.Sprite).spriteFrame = this.picFrames[frameIndex]
        if (this.transitionType == FrameTransitionType.FadeIn) {
            let tranNode = this.node.getChildByName('TransitionNode')
            let nextFrameIndex = (this.currentIndex + 1) % this.frameIndexArray.length;
            tranNode.getComponent(cc.Sprite).spriteFrame = this.picFrames[this.frameIndexArray[nextFrameIndex]]
            tranNode.opacity = 0;
        }
        this.currentIndex++;
        if (false == this.loop && this.currentIndex >= this.frameIndexArray.length) {
            this.emitDoneEvent();
            this.enabled = false;
            return;
        }
        this.currentIndex %= this.frameIndexArray.length;
    }

    pauseTask() {
        super.pauseTask();
        this.isPaused = true;
    }

    resmueTask() {
        super.resmueTask();
        this.isPaused = false;
    }

    stopTask() {
        super.stopTask();
        this.isPaused = true;
    }

    private timePassed = 0;
    update(dt) {
        if (this.isPaused)
            return;
        this.timePassed += dt;
        if (this.transitionType == FrameTransitionType.FadeIn) {
            let tranNode = this.node.getChildByName('TransitionNode')
            tranNode && (tranNode.opacity = this.timePassed / this.frameDuration * 255) 
        }
        if (this.timePassed >= this.frameDuration) {
            this.changeFrame();
            this.timePassed = 0;
        }
    }
}
